{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/opt/miniconda3/envs/MindSpore/lib/python3.9/site-packages/mindquantum/simulator/__init__.py:17: UserWarning: Unable import mqvector gpu backend due to: cannot import name '_mq_vector_gpu' from partially initialized module 'mindquantum' (most likely due to a circular import) (/opt/miniconda3/envs/MindSpore/lib/python3.9/site-packages/mindquantum/__init__.py)\n",
      "  from .available_simulator import SUPPORTED_SIMULATOR\n",
      "Please first ``pip install -U qiskit`` to enable related functionality in translation module\n"
     ]
    }
   ],
   "source": [
    "\n",
    "from mindquantum.algorithm.nisq import HardwareEfficientAnsatz,RYFull\n",
    "from mindquantum.core.parameterresolver import  PRGenerator\n",
    "import numpy as np\n",
    "from mindquantum.core.gates import RX, RY, RZ, H, X, Y, Z, I,CNOT\n",
    "from mindquantum.core.circuit import Circuit,UN\n",
    "import mindspore as ms\n",
    "import pickle\n",
    "from mindquantum.core.parameterresolver import PRGenerator\n",
    "import random\n",
    "from mindspore import Tensor,ops\n",
    "import tensorcircuit as tc\n",
    "import tensorflow as tf\n",
    "import mindspore.numpy as mnp\n",
    "from DQAS_tool import wash_pr,Mindspore_ansatz_micro,best_from_structure\n",
    "from DQAS_tool import  sampling_from_structure,zeroslike_grad_nnp_micro_minipool,nmf_gradient,vag_nnp_micro,DQAS_accuracy,Washing_namemap\n",
    "import sys\n",
    "from typing import Union\n",
    "sys.path.append('..')\n",
    "from Test_tool import Test_ansatz\n",
    "from data_processing import X_train,X_test,y_train,y_test\n",
    "from mindquantum.core.circuit import change_param_name,apply\n",
    "\n",
    "pr_pool = PRGenerator('pool')\n",
    "parameterized_circuit= \\\n",
    "[\n",
    " UN(RZ(pr_pool.new()),maps_obj=[0])+\\\n",
    " UN(RY(pr_pool.new()),maps_obj=[0])+\\\n",
    " UN(RZ(pr_pool.new()),maps_obj=[0])+I.on(1),\n",
    " UN(RZ(pr_pool.new()),maps_obj=[1])+\\\n",
    " UN(RY(pr_pool.new()),maps_obj=[1])+\\\n",
    " UN(RZ(pr_pool.new()),maps_obj=[1])+I.on(0),]\n",
    "\n",
    "\n",
    "unparameterized_circuit = \\\n",
    "[UN(X,maps_obj=[0],maps_ctrl=[1]),\n",
    " UN(X,maps_obj=[1],maps_ctrl=[0]),\n",
    " ]\n",
    "ansatz_pr = PRGenerator('ansatz')\n",
    "shape_parametized = len(parameterized_circuit)\n",
    "shape_unparameterized = len(unparameterized_circuit)\n",
    "num_layer=4\n",
    "shape_nnp = (7,num_layer,shape_parametized,3)\n",
    "shape_stp = (num_layer,shape_unparameterized+shape_parametized)\n",
    "stddev = 0.03\n",
    "np.random.seed(2)\n",
    "nnp = np.random.normal(loc=0.0, scale=stddev, size=shape_nnp)\n",
    "stp = np.random.normal(loc=0.0, scale=stddev, size=shape_stp)\n",
    "ops_onehot = ops.OneHot(axis=-1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/svg+xml": [
       "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"396.8\" height=\"80.0\" xmlns:xlink=\"http://www.w3.org/1999/xlink\"><rect x=\"0\" y=\"0.0\" width=\"396.8\" height=\"80.0\" fill=\"#ffffff\" /><text x=\"20.0\" y=\"40.0\" font-size=\"16px\" dominant-baseline=\"middle\" text-anchor=\"start\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#252b3a\" >q0: </text><line x1=\"48.8\" x2=\"376.8\" y1=\"40.0\" y2=\"40.0\" stroke=\"#adb0b8\" stroke-width=\"1\" /><rect x=\"72.8\" y=\"20.0\" width=\"80.0\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#fac209\" fill-opacity=\"1\" /><text x=\"112.8\" y=\"36.0\" font-size=\"20px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >RZ </text><text x=\"112.8\" y=\"52.0\" font-size=\"14.0px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >pool0 </text><rect x=\"172.8\" y=\"20.0\" width=\"80.0\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#fac209\" fill-opacity=\"1\" /><text x=\"212.8\" y=\"36.0\" font-size=\"20px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >RY </text><text x=\"212.8\" y=\"52.0\" font-size=\"14.0px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >pool1 </text><rect x=\"272.8\" y=\"20.0\" width=\"80.0\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#fac209\" fill-opacity=\"1\" /><text x=\"312.8\" y=\"36.0\" font-size=\"20px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >RZ </text><text x=\"312.8\" y=\"52.0\" font-size=\"14.0px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >pool2 </text></svg>"
      ],
      "text/plain": [
       "<mindquantum.io.display.circuit_svg_drawer.SVGCircuit at 0x110c99eb0>"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "pr_pool = PRGenerator('pool')\n",
    "cir = UN(RZ(pr_pool.new()),maps_obj=[0])+\\\n",
    " UN(RY(pr_pool.new()),maps_obj=[0])+\\\n",
    " UN(RZ(pr_pool.new()),maps_obj=[0])\n",
    "\n",
    "cir.svg()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from DQAS_tool import  sampling_from_structure,vag_nnp_micro_minipool,zeroslike_grad_nnp_micro_minipool,nmf_gradient,DQAS_accuracy,Mindspore_ansatz_micro_minipool,nnp_dealwith\n",
    "#from DQAS_tool import  DQASAnsatz_from_result,DQAS_accuracy\n",
    "K = tc.set_backend(\"tensorflow\")\n",
    "lr = tf.keras.optimizers.schedules.ExponentialDecay(0.06, 100, 0.5)\n",
    "structure_opt = tc.backend.optimizer(tf.keras.optimizers.Adam(0.1))\n",
    "network_opt = tc.backend.optimizer(tf.keras.optimizers.Adam(lr))\n",
    "verbose = False\n",
    "# 设置超参数\n",
    "epochs = 100\n",
    "batch_size=100\n",
    "avcost1 = 0\n",
    "ops_onehot = ops.OneHot(axis=-1)\n",
    "batch_loss_history=[] # 记录每个epoch的batch_size损失值\n",
    "structure_distribution_history=[] # 记录每个epoch的结构参数\n",
    "ansatz_params_history=[] # 记录每个epoch的网络参数\n",
    "best_candidates_history=[] # 记录每个epoch的最佳候选\n",
    "acc_history = [] #记录每个epoch的准确率\n",
    "\n",
    " \n",
    "for epoch in range(epochs):  # 更新结构参数的迭代\n",
    "    avcost2 = avcost1\n",
    "    costl = []\n",
    "    tmp = np.stack([sampling_from_structure(stp,num_layer,shape_parametized) for _ in range(batch_size)])\n",
    "    batch_structure = ops_onehot(ms.Tensor(tmp),shape_parametized+shape_unparameterized,ms.Tensor(1),ms.Tensor(0))\n",
    "    #print(batch_structure.shape)\n",
    "    # print(tmp,batch_structure)\n",
    "    loss_value = []\n",
    "    grad_nnps = []\n",
    "    grad_stps = []\n",
    "    \n",
    "    for i in batch_structure:\n",
    "        #print(ops.Argmax()(i))          \n",
    "        infd, grad_nnp = vag_nnp_micro_minipool(Structure_params=i,\n",
    "                                    Ansatz_params=nnp,\n",
    "                                    paramerterized_pool=parameterized_circuit,  unparamerterized_pool=unparameterized_circuit,\n",
    "                                    num_layer=num_layer,n_qbits=8)(ms.Tensor(X_train),ms.Tensor(y_train))\n",
    "        \n",
    "        grad_nnp_zeroslike = zeroslike_grad_nnp_micro_minipool(batch_sturcture=i,grad_nnp=grad_nnp[0],shape_parametized=shape_parametized,ansatz_parameters=nnp)\n",
    "        gs = nmf_gradient(structures=stp,oh=i,num_layer=num_layer,size_pool=stp.shape[1])\n",
    "        #print(infd,grad_nnp)\n",
    "        loss_value.append(infd)\n",
    "        grad_nnps.append(ms.Tensor(grad_nnp_zeroslike,dtype=ms.float64))\n",
    "        grad_stps.append(gs)\n",
    "\n",
    "      \n",
    "    infd = ops.stack(loss_value)\n",
    "    gnnp = ops.addn(grad_nnps)\n",
    "    gstp = [(infd[i] - avcost2) * grad_stps[i] for i in range(infd.shape[0])]\n",
    "    gstp_averge = ops.addn(gstp) / infd.shape[0]\n",
    "    avcost1 = sum(infd) / infd.shape[0]\n",
    "    # print(f'loss={infd}\\ngrad_nnp={gnnp}\\ngrandient_stp={gstp_averge}')\n",
    "    \n",
    "    gnnp_tf = tf.convert_to_tensor(gnnp.asnumpy(),dtype=tf.float64)\n",
    "    nnp_tf = tf.convert_to_tensor(nnp,dtype=tf.float64)\n",
    "    gstp_averge_tf = tf.convert_to_tensor(gstp_averge.reshape(stp.shape).asnumpy(),dtype=tf.float64)\n",
    "    stp_tf = tf.convert_to_tensor(stp,dtype=tf.float64)\n",
    "     # 更新一步参数\n",
    "    nnp_tf = network_opt.update(gnnp_tf, nnp_tf)\n",
    "    stp_tf = structure_opt.update(gstp_averge_tf, stp_tf) \n",
    "    \n",
    "    nnp = nnp_tf.numpy()\n",
    "    stp = stp_tf.numpy()\n",
    "\n",
    "    batch_loss_history.append(avcost1)\n",
    "    structure_distribution_history.append(stp)\n",
    "    ansatz_params_history.append(nnp)\n",
    "    #best_candidates_history.append(best_from_structure(cand_preset.asnumpy()))\n",
    "    cand_preset = best_from_structure(stp)\n",
    "    best_candidates_history.append(cand_preset.asnumpy())\n",
    "    \n",
    "\n",
    "    if epoch % 1 == 0 or epoch == epochs - 1:\n",
    "        print(\"----------epoch %s-----------\" % epoch)\n",
    "        print(\n",
    "            \"batched平均损失: \",\n",
    "            avcost1,\n",
    "        )\n",
    "    \n",
    "        if verbose:\n",
    "            print(\n",
    "                \"strcuture parameter: \\n\",\n",
    "                stp,\n",
    "                \"\\n network parameter: \\n\",\n",
    "                nnp,\n",
    "            )\n",
    "        \n",
    "        print(\"最好的候选结构:\",cand_preset)\n",
    "        stp_for_test = ops_onehot(ms.Tensor(cand_preset),shape_parametized+shape_unparameterized,ms.Tensor(1),ms.Tensor(0))\n",
    "\n",
    "        \n",
    "        if cand_preset.min() <shape_parametized:\n",
    "            ansatz_parameters = nnp_dealwith(Structure_params=stp_for_test,Network_params=nnp)\n",
    "            test_ansatz = Mindspore_ansatz_micro_minipool(Structure_p=stp_for_test,\n",
    "                                            parameterized_pool=parameterized_circuit,unparameterized_pool=unparameterized_circuit,\n",
    "                                            num_layer=num_layer,\n",
    "                                            n_qbits=8)\n",
    "            acc = DQAS_accuracy(ansatz=test_ansatz,Network_params=ansatz_parameters,n_qbits=8)\n",
    "            acc_history.append(acc)\n",
    "            print(f'二分类准确率 Acc ={acc*100}% ')\n",
    "        \n",
    "        #我想每一轮结束 保存batch_loss_history、structure_distribution_history、ansatz_params_history、best_candidates_history、acc_history\n",
    "                # 保存数据\n",
    "        with open('training_history-minipool-k4.pkl', 'wb') as f:\n",
    "            pickle.dump({\n",
    "                'batch_loss_history': batch_loss_history,\n",
    "                'structure_distribution_history': structure_distribution_history,\n",
    "                'ansatz_params_history': ansatz_params_history,\n",
    "                'best_candidates_history': best_candidates_history,\n",
    "                'acc_history': acc_history\n",
    "            }, f)\n",
    "        \n",
    "        "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "由于 DQAS 在量子结构搜索的过程中进行结构、参数的双优化.  \n",
    "我们可以在结构基本不再变动时停止搜索过程转为单优化 效率更高"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "MindSpore",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.19"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
